import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox, filedialog
import re
import os
from pathlib import Path

class FindReferencesApp:
    def __init__(self, root):
        self.root = root
        self.root.title("引用查找工具")
        self.root.geometry("1000x600")
        self.root.configure(bg="#1E1E1E")
        
        # 设置字体，确保中文正常显示
        self.default_font = ('SimHei', 10)
        
        # 当前打开的文件和选中的引用
        self.current_file = None
        self.current_reference = None
        self.current_directory = ""
        self.current_files = []
        
        # 上下文行数（当前行上下显示的行数）
        self.context_lines = 10
        
        # 调试日志
        self.debug_logs = []
        
        # 创建UI
        self._create_ui()
        
        # 示例引用数据
        self.sample_references = self._get_sample_references()
        
        # 清空搜索框
        self.search_entry.delete(0, tk.END)
        
        # 状态栏提示
        self.status_label.config(text="请选择目录或文件，然后输入搜索词")
    
    def _create_ui(self):
        """创建用户界面"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding=0)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 顶部控制栏
        control_frame = ttk.Frame(main_frame, padding=5)
        control_frame.pack(fill=tk.X)
        
        # 文件选择区域
        file_frame = ttk.Frame(control_frame)
        file_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        
        ttk.Label(file_frame, text="项目目录:", font=self.default_font).pack(side=tk.LEFT, padx=5)
        self.dir_entry = ttk.Entry(file_frame, width=35, font=self.default_font)
        self.dir_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        
        browse_dir_btn = ttk.Button(file_frame, text="浏览目录...", command=self._browse_directory)
        browse_dir_btn.pack(side=tk.LEFT, padx=5)
        
        browse_files_btn = ttk.Button(file_frame, text="选择文件...", command=self._browse_files)
        browse_files_btn.pack(side=tk.LEFT, padx=5)
        
        # 搜索区域
        search_frame = ttk.Frame(control_frame)
        search_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        
        ttk.Label(search_frame, text="搜索:", font=self.default_font).pack(side=tk.LEFT, padx=5)
        self.search_entry = ttk.Entry(search_frame, width=30, font=self.default_font)
        self.search_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        
        search_btn = ttk.Button(search_frame, text="查找引用", command=self._search_references, width=15)
        search_btn.pack(side=tk.LEFT, padx=5)
        
        # 调试区域
        debug_frame = ttk.Frame(control_frame)
        debug_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        
        ttk.Label(debug_frame, text="调试:", font=self.default_font).pack(side=tk.LEFT, padx=5)
        self.debug_var = tk.BooleanVar()
        self.debug_check = ttk.Checkbutton(debug_frame, text="启用日志", variable=self.debug_var)
        self.debug_check.pack(side=tk.LEFT, padx=5)
        
        self.clear_logs_btn = ttk.Button(debug_frame, text="清除日志", command=self._clear_logs)
        self.clear_logs_btn.pack(side=tk.LEFT, padx=5)
        
        # 分割窗口
        paned_window = ttk.PanedWindow(main_frame, orient=tk.VERTICAL)
        paned_window.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 上部代码查看器
        upper_frame = ttk.Frame(paned_window)
        paned_window.add(upper_frame, weight=3)
        
        # 代码查看器滚动条
        code_scrollbar = ttk.Scrollbar(upper_frame)
        code_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 代码文本区域
        self.code_text = scrolledtext.ScrolledText(upper_frame, wrap=tk.WORD, 
                                                  font=('Consolas', 10),
                                                  bg="#1E1E1E", fg="#D4D4D4",
                                                  insertbackground="#FFFFFF",
                                                  yscrollcommand=code_scrollbar.set)
        self.code_text.pack(fill=tk.BOTH, expand=True)
        code_scrollbar.config(command=self.code_text.yview)
        
        # 下部调试日志
        lower_frame = ttk.LabelFrame(paned_window, text="调试日志", padding=5)
        paned_window.add(lower_frame, weight=1)
        
        # 日志滚动条
        log_scrollbar = ttk.Scrollbar(lower_frame)
        log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 日志文本区域
        self.log_text = scrolledtext.ScrolledText(lower_frame, wrap=tk.WORD, 
                                                 font=('Consolas', 9),
                                                 bg="#1E1E1E", fg="#999999",
                                                 yscrollcommand=log_scrollbar.set)
        self.log_text.pack(fill=tk.BOTH, expand=True)
        log_scrollbar.config(command=self.log_text.yview)
        
        # 状态栏
        status_frame = ttk.Frame(self.root, relief=tk.SUNKEN, padding=3)
        status_frame.pack(side=tk.BOTTOM, fill=tk.X)
        
        self.status_label = ttk.Label(status_frame, text="就绪", anchor=tk.W)
        self.status_label.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        self.position_label = ttk.Label(status_frame, text="行: 0 | 列: 0", width=20)
        self.position_label.pack(side=tk.RIGHT)
        
        # 绑定鼠标移动事件更新位置
        self.code_text.bind("<Motion>", self._update_cursor_position)
        self.code_text.bind("<ButtonRelease-1>", self._update_cursor_position)
    
    def _log(self, message):
        """添加日志消息"""
        self.debug_logs.append(message)
        if self.debug_var.get():
            self.log_text.insert(tk.END, f"{message}\n")
            self.log_text.see(tk.END)
    
    def _clear_logs(self):
        """清除所有日志"""
        self.debug_logs = []
        self.log_text.delete(1.0, tk.END)
    
    def _get_sample_references(self):
        """获取示例引用数据"""
        return {
            "shopping-cart.js": [
                {"line": 15, "context": "function calculateTotal(prices) {", "code": [
                    "/**",
                    " * Shopping Cart Module",
                    " * Handles cart operations and total calculation",
                    " */",
                    "import { formatCurrency } from './utils.js';",
                    "",
                    "export class ShoppingCart {",
                    "  constructor() {",
                    "    this.items = [];",
                    "  }",
                    "",
                    "  addItem(item) {",
                    "    this.items.push(item);",
                    "  }",
                    "",
                    "  removeItem(itemId) {",
                    "    this.items = this.items.filter(item => item.id !== itemId);",
                    "  }",
                    "",
                    "  function calculateTotal(prices) {",
                    "    return prices.reduce((total, price) => total + price, 0);",
                    "  }",
                    "",
                    "  getTotal() {",
                    "    const prices = this.items.map(item => item.price);",
                    "    return calculateTotal(prices);",
                    "  }",
                    "",
                    "  getFormattedTotal() {",
                    "    return formatCurrency(this.getTotal());",
                    "  }",
                    "}",
                    "",
                    "// Example usage",
                    "const cart = new ShoppingCart();",
                    "cart.addItem({ id: 1, name: 'Laptop', price: 999.99 });",
                    "cart.addItem({ id: 2, name: 'Mouse', price: 29.99 });",
                    "cart.addItem({ id: 3, name: 'Keyboard', price: 79.99 });",
                    "",
                    "const total = calculateTotal(items.map(item => item.price));",
                    "console.log('Total:', total); // 1109.97"
                ]},
                {"line": 42, "context": "const total = calculateTotal(items.map(item => item.price));", "code": []}
            ],
            "checkout.js": [
                {"line": 28, "context": "const orderTotal = calculateTotal(cartItems);", "code": []},
                {"line": 76, "context": "if (calculateTotal(discountedItems) < minOrderAmount) {", "code": []}
            ]
        }
    
    def _browse_directory(self):
        """浏览并选择目录"""
        directory = filedialog.askdirectory(title="选择项目目录")
        if directory:
            self.current_directory = directory
            self.current_files = []  # 清除已选文件
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, directory)
            self.status_label.config(text=f"已选择目录: {directory}")
            self._log(f"[目录选择] 已选择目录: {directory}")
    
    def _browse_files(self):
        """浏览并选择多个文件"""
        files = filedialog.askopenfilenames(
            title="选择文件",
            filetypes=[("所有代码文件", "*.py;*.js;*.java;*.html;*.css;*.cpp;*.c;*.cs;*.php"),
                       ("Python文件", "*.py"),
                       ("JavaScript文件", "*.js"),
                       ("Java文件", "*.java"),
                       ("HTML文件", "*.html"),
                       ("CSS文件", "*.css"),
                       ("所有文件", "*.*")]
        )
        
        if files:
            self.current_files = files
            self.current_directory = ""  # 清除已选目录
            
            # 显示已选择的文件数量
            file_count = len(files)
            file_text = f"{file_count}个文件" if file_count > 1 else os.path.basename(files[0])
            
            self.dir_entry.delete(0, tk.END)
            self.dir_entry.insert(0, f"已选择 {file_text}")
            self.status_label.config(text=f"已选择 {file_count} 个文件")
            self._log(f"[文件选择] 已选择 {file_count} 个文件")
            for file in files:
                self._log(f"[文件选择] 选择的文件: {os.path.basename(file)}")
    
    def _search_references(self):
        """搜索引用"""
        search_term = self.search_entry.get().strip()
        directory = self.dir_entry.get().strip()
        
        if not search_term:
            messagebox.showwarning("警告", "请输入搜索词")
            return
        
        self._log(f"[搜索] 开始搜索: '{search_term}'")
        
        # 如果没有选择目录或文件，使用示例数据
        if not directory and not self.current_directory and not self.current_files:
            self._load_sample_data()
            self._highlight_search_term(search_term)
            self.status_label.config(text=f"使用示例数据 - 找到 {sum(len(refs) for refs in self.sample_references.values())} 个引用")
            self._log(f"[搜索] 使用示例数据 - 找到 {sum(len(refs) for refs in self.sample_references.values())} 个引用")
            return
        
        # 更新状态栏
        if self.current_files:
            search_location = f"{len(self.current_files)}个文件"
        else:
            search_location = directory or self.current_directory
            
        self.status_label.config(text=f"搜索中: {search_term} in {search_location}")
        self._log(f"[搜索] 搜索位置: {search_location}")
        self.root.update()
        
        # 实际的文件搜索逻辑
        try:
            if self.current_files:
                self._log(f"[搜索] 在 {len(self.current_files)} 个文件中搜索")
                references = self._find_references_in_files(self.current_files, search_term)
            else:
                self._log(f"[搜索] 在目录 {directory} 中搜索")
                references = self._find_references_in_directory(directory or self.current_directory, search_term)
            
            self._display_search_results(references, search_term)
            result_count = sum(len(refs) for refs in references.values())
            self.status_label.config(text=f"搜索完成: 找到 {result_count} 个引用")
            self._log(f"[搜索] 完成 - 找到 {result_count} 个引用")
        except Exception as e:
            messagebox.showerror("错误", f"搜索过程中出错: {str(e)}")
            self.status_label.config(text="搜索出错")
            self._log(f"[错误] 搜索过程中出错: {str(e)}")
    
    def _find_references_in_directory(self, directory, search_term):
        """在目录中查找引用"""
        references = {}
        file_extensions = ['.py', '.js', '.java', '.html', '.css', '.cpp', '.c', '.cs', '.php']  # 要搜索的文件类型
        
        self._log(f"[文件扫描] 开始扫描目录: {directory}")
        
        file_count = 0
        match_count = 0
        
        for root, _, files in os.walk(directory):
            for file in files:
                if any(file.endswith(ext) for ext in file_extensions):
                    file_count += 1
                    file_path = os.path.join(root, file)
                    try:
                        with open(file_path, 'r', encoding='utf-8') as f:
                            content = f.readlines()
                            file_matches = 0
                            for line_num, line in enumerate(content, 1):
                                if search_term in line:
                                    if file not in references:
                                        references[file] = []
                                    
                                    # 获取上下文（行号和包含搜索词的行）
                                    references[file].append({
                                        "line": line_num,
                                        "context": line.strip(),
                                        "code": content,
                                        "file_path": file_path
                                    })
                                    file_matches += 1
                                    match_count += 1
                            
                            if file_matches > 0:
                                self._log(f"[文件扫描] 在文件 {file} 中找到 {file_matches} 个匹配")
                    except Exception as e:
                        self._log(f"[警告] 无法读取文件 {file_path}: {str(e)}")
        
        self._log(f"[文件扫描] 扫描完成: 共扫描 {file_count} 个文件，找到 {match_count} 个匹配")
        return references
    
    def _find_references_in_files(self, files, search_term):
        """在多个文件中查找引用"""
        references = {}
        
        self._log(f"[文件扫描] 开始扫描 {len(files)} 个文件")
        
        file_count = 0
        match_count = 0
        
        for file_path in files:
            file_count += 1
            try:
                file_name = os.path.basename(file_path)
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.readlines()
                    file_matches = 0
                    for line_num, line in enumerate(content, 1):
                        if search_term in line:
                            if file_name not in references:
                                references[file_name] = []
                            
                            # 获取上下文（行号和包含搜索词的行）
                            references[file_name].append({
                                "line": line_num,
                                "context": line.strip(),
                                "code": content,
                                "file_path": file_path
                            })
                            file_matches += 1
                            match_count += 1
                    
                    if file_matches > 0:
                        self._log(f"[文件扫描] 在文件 {file_name} 中找到 {file_matches} 个匹配")
            except Exception as e:
                self._log(f"[警告] 无法读取文件 {file_path}: {str(e)}")
        
        self._log(f"[文件扫描] 扫描完成: 共扫描 {file_count} 个文件，找到 {match_count} 个匹配")
        return references
    
    def _display_search_results(self, references, search_term):
        """显示搜索结果"""
        # 清空现有数据
        for item in self.results_tree.get_children():
            self.results_tree.delete(item)
        
        # 添加搜索结果
        for file, refs in references.items():
            if refs:  # 只添加有引用的文件
                parent = self.results_tree.insert("", tk.END, text=file, open=False)
                for ref in refs:
                    self.results_tree.insert(parent, tk.END, values=(ref["line"], ref["context"]), 
                                            tags=(f"file_{file}", f"line_{ref['line']}"))
        
        # 如果有结果，默认打开第一个文件
        if self.results_tree.get_children():
            first_file = self.results_tree.get_children()[0]
            self.results_tree.item(first_file, open=True)
            self._log(f"[结果显示] 显示搜索结果 - {len(references)} 个文件中有匹配")
        else:
            self.status_label.config(text=f"搜索完成: 未找到 '{search_term}' 的引用")
            self._log(f"[结果显示] 未找到匹配结果")
    
    def _on_item_click(self, event):
        """处理树视图项点击事件"""
        region = self.results_tree.identify_region(event.x, event.y)
        item = self.results_tree.identify_row(event.y)
        
        if not item:
            return
            
        # 获取项的值
        values = self.results_tree.item(item, "values")
        
        # 如果点击的是文件节点（没有值），则显示整个文件
        if not values:
            file_name = self.results_tree.item(item, "text")
            self.current_file = file_name
            self.current_reference = None
            
            self._log(f"[文件选择] 选择文件: {file_name}")
            
            # 更新代码查看器，显示整个文件
            self._update_code_viewer(file_name, show_full=True)
    
    def _on_reference_select(self, event):
        """处理引用选择事件"""
        selected_item = self.results_tree.selection()
        if not selected_item:
            return
        
        item = selected_item[0]
        values = self.results_tree.item(item, "values")
        
        if not values:  # 如果是文件节点而不是引用节点
            return
        
        line_num = values[0]
        file_item = self.results_tree.parent(item)
        file_name = self.results_tree.item(file_item, "text")
        
        self.current_file = file_name
        self.current_reference = line_num
        
        self._log(f"[引用选择] 选择引用: {file_name}:{line_num}")
        
        # 更新代码查看器，显示带上下文的代码片段
        self._update_code_viewer(file_name, line_num=line_num, show_full=False)
    
    def _update_code_viewer(self, file_name, line_num=None, show_full=False):
        """更新代码查看器内容"""
        self._log(f"[代码查看器] 开始更新 - 文件: {file_name}, 显示完整内容: {show_full}, 行号: {line_num}")
        
        # 清空代码查看器
        self.code_text.delete(1.0, tk.END)
        
        # 显示加载中提示
        self.code_text.insert(tk.END, "加载中...", "loading")
        self.code_text.tag_config("loading", foreground="#888888", justify=tk.CENTER)
        self.root.update_idletasks()
        
        # 如果有选择的文件，尝试读取实际文件
        file_path = None
        content = None
        
        # 尝试从当前选择的文件中查找
        if self.current_files:
            self._log(f"[代码查看器] 尝试从已选文件中查找: {file_name}")
            file_path = next((f for f in self.current_files if os.path.basename(f) == file_name), None)
            if file_path:
                self._log(f"[代码查看器] 找到文件路径: {file_path}")
                try:
                    self._log(f"[代码查看器] 尝试打开文件: {file_path}")
                    with open(file_path, 'r', encoding='utf-8') as f:
                        content = f.read()  # 读取为字符串
                        self._log(f"[代码查看器] 成功读取文件内容 - 字符数: {len(content)}")
                        
                        if content:
                            # 转换为行列表，保留行结束符
                            content = content.splitlines(True)
                            self._log(f"[代码查看器] 转换为行列表 - 行数: {len(content)}")
                        else:
                            content = []
                except Exception as e:
                    content = None
                    self._show_error(f"无法读取文件: {str(e)}")
                    self._log(f"[错误] 无法读取文件: {str(e)}")
            else:
                self._log(f"[代码查看器] 未在已选文件中找到: {file_name}")
        
        # 如果没找到，尝试从目录中查找
        if not content and self.current_directory and os.path.isdir(self.current_directory):
            self._log(f"[代码查看器] 尝试从目录中查找: {file_name}")
            file_path = os.path.join(self.current_directory, file_name)
            self._log(f"[代码查看器] 构建文件路径: {file_path}")
            try:
                self._log(f"[代码查看器] 尝试打开文件: {file_path}")
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()  # 读取为字符串
                    self._log(f"[代码查看器] 成功读取文件内容 - 字符数: {len(content)}")
                    
                    if content:
                        # 转换为行列表，保留行结束符
                        content = content.splitlines(True)
                        self._log(f"[代码查看器] 转换为行列表 - 行数: {len(content)}")
                    else:
                        content = []
            except Exception as e:
                content = None
                self._show_error(f"无法读取文件: {str(e)}")
                self._log(f"[错误] 无法读取文件: {str(e)}")
        
        # 如果还没找到，尝试从示例数据中查找
        if not content and file_name in self.sample_references:
            self._log(f"[代码查看器] 尝试从示例数据中查找: {file_name}")
            # 找到第一个有完整代码的引用
            for ref in self.sample_references[file_name]:
                if ref["code"]:
                    content = ref["code"]
                    self._log(f"[代码查看器] 从示例数据中获取内容 - 行数: {len(content)}")
                    break
            if not content:
                self._show_error("示例数据中没有此文件的完整内容")
                self._log(f"[错误] 示例数据中没有此文件的完整内容")
        
        # 如果还是没找到，显示错误
        if not content:
            if not file_path:
                self._show_error("找不到指定的文件")
                self._log(f"[错误] 找不到指定的文件: {file_name}")
            return
        
        # 清空加载提示
        self.code_text.delete(1.0, tk.END)
        
        # 显示文件内容
        if content:  # 确保文件内容不为空
            self._log(f"[代码查看器] 开始显示内容 - 行数: {len(content)}")
            if show_full:
                self._display_full_file(content)
                self._log(f"[代码查看器] 显示完整文件内容")
            elif line_num is not None:
                self._display_code_with_context(content, int(line_num))
                self._log(f"[代码查看器] 显示代码片段 - 行号: {line_num}")
            else:
                self._display_full_file(content)
                self._log(f"[代码查看器] 显示完整文件内容")
            
            # 更新状态栏
            if self.current_files:
                file_path = next((ref["file_path"] for ref_list in self.sample_references.values() 
                                 for ref in ref_list if ref.get("file_path") and os.path.basename(ref["file_path"]) == file_name), 
                                file_name)
            else:
                directory = self.dir_entry.get().strip() or self.current_directory
                file_path = os.path.join(directory, file_name) if directory else file_name
                
            status_text = f"当前文件: {os.path.basename(file_path)}"
            if show_full:
                status_text += " | 显示全量内容"
            else:
                status_text += f" | 行: {line_num} | 显示代码片段"
                
            self.status_label.config(text=status_text)
        else:
            self._show_error("文件为空")
            self._log(f"[错误] 文件为空: {file_name}")
    
    def _show_error(self, message):
        """在代码查看器中显示错误消息"""
        self.code_text.delete(1.0, tk.END)
        self.code_text.insert(tk.END, f"// 错误: {message}\n", "error")
        self.code_text.tag_config("error", foreground="#FF6B6B", justify=tk.CENTER)
        self._log(f"[错误显示] {message}")
    
    def _display_code_with_context(self, content, line_num):
        """显示带有上下文的代码片段"""
        context = int(self.context_spinbox.get())
        start_line = max(1, line_num - context)
        end_line = min(len(content), line_num + context)
        
        self._log(f"[代码查看器] 显示代码片段 - 起始行: {start_line}, 结束行: {end_line}, 当前行: {line_num}")
        
        # 添加省略号表示有更多内容
        if start_line > 1:
            self.code_text.insert(tk.END, "...\n", "ellipsis")
        
        # 显示上下文代码
        for i in range(start_line, end_line + 1):
            line_content = content[i-1]  # 行内容已包含行结束符
            line_tag = "line"
            if i == line_num:
                line_tag = "current_line"
            
            # 插入行号和代码
            self.code_text.insert(tk.END, f"{i:4d}  ", "linenum")
            self.code_text.insert(tk.END, line_content, line_tag)
        
        # 添加省略号表示有更多内容
        if end_line < len(content):
            self.code_text.insert(tk.END, "...\n", "ellipsis")
        
        # 配置标签样式
        self.code_text.tag_config("linenum", foreground="#666666", justify=tk.RIGHT)
        self.code_text.tag_config("ellipsis", foreground="#666666", justify=tk.CENTER)
        self.code_text.tag_config("current_line", background="#3A3D41", foreground="#FFFFFF")
    
    def _display_full_file(self, content):
        """显示整个文件内容"""
        self._log(f"[代码查看器] 显示完整文件 - 总行数: {len(content)}")
        
        for i, line in enumerate(content, 1):
            line_content = line  # 行内容已包含行结束符
            
            # 插入行号和代码
            self.code_text.insert(tk.END, f"{i:4d}  ", "linenum")
            self.code_text.insert(tk.END, line_content, "line")
        
        # 配置标签样式
        self.code_text.tag_config("linenum", foreground="#666666", justify=tk.RIGHT)
    
    def _highlight_current_line(self, line_num):
        """高亮当前选中的行"""
        # 清除之前的高亮
        self.code_text.tag_remove("current_line", 1.0, tk.END)
        self.code_text.tag_remove("search_term", 1.0, tk.END)
        
        # 设置当前行高亮
        start_pos = f"{line_num}.0"
        end_pos = f"{line_num}.end"
        
        self.code_text.tag_add("current_line", start_pos, end_pos)
        self.code_text.tag_config("current_line", background="#3A3D41", foreground="#FFFFFF")
        
        # 滚动到当前行
        self.code_text.see(start_pos)
        
        # 高亮搜索词
        search_term = self.search_entry.get().strip()
        if search_term:
            self._highlight_search_term(search_term)
    
    def _highlight_search_term(self, term):
        """高亮搜索词"""
        # 设置搜索词高亮
        self.code_text.tag_config("search_term", background="#61AFEF", foreground="#000000")
        
        # 在文本中查找并高亮所有匹配项
        text = self.code_text.get(1.0, tk.END)
        start_pos = 1.0
        
        while True:
            start_pos = self.code_text.search(term, start_pos, stopindex=tk.END)
            if not start_pos:
                break
            
            end_pos = f"{start_pos}+{len(term)}c"
            
            # 确保搜索词不在行号区域
            line, _ = start_pos.split('.')
            line_start = f"{line}.0"
            line_end = f"{line}.4"  # 行号宽度
            
            if self.code_text.compare(line_start, '<=', start_pos) and self.code_text.compare(start_pos, '<', line_end):
                start_pos = end_pos  # 跳过行号区域的匹配
                continue
            
            self.code_text.tag_add("search_term", start_pos, end_pos)
            start_pos = end_pos
    
    def _update_cursor_position(self, event=None):
        """更新光标位置显示"""
        position = self.code_text.index(tk.INSERT)
        line, column = position.split('.')
        self.position_label.config(text=f"行: {line} | 列: {column}")
    
    def _load_sample_data(self):
        """加载示例数据到界面"""
        # 清空现有数据
        for item in self.results_tree.get_children():
            self.results_tree.delete(item)
        
        # 只有在用户没有选择目录或文件时才使用示例数据
        if not self.current_directory and not self.current_files:
            search_term = self.search_entry.get().strip()
            if search_term:
                self._log(f"[示例数据] 加载示例数据 - 搜索词: {search_term}")
                # 添加示例数据
                for file, references in self.sample_references.items():
                    file_references = [ref for ref in references if search_term in ref["context"]]
                    if file_references:
                        parent = self.results_tree.insert("", tk.END, text=file, open=False)
                        for ref in file_references:
                            self.results_tree.insert(parent, tk.END, values=(ref["line"], ref["context"]), 
                                                    tags=(f"file_{file}", f"line_{ref['line']}"))
                
                # 如果有结果，默认打开第一个文件
                if self.results_tree.get_children():
                    first_file = self.results_tree.get_children()[0]
                    self.results_tree.item(first_file, open=True)
                    self._log(f"[示例数据] 加载完成 - 找到 {len(self.results_tree.get_children())} 个文件有匹配")

if __name__ == "__main__":
    root = tk.Tk()
    app = FindReferencesApp(root)
    # 添加结果树视图
    results_frame = ttk.Frame(root)
    results_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
    
    # 创建结果树视图
    columns = ("Line", "Context")
    app.results_tree = ttk.Treeview(results_frame, columns=columns, show="headings")
    app.results_tree.heading("Line", text="行号")
    app.results_tree.heading("Context", text="上下文")
    app.results_tree.column("Line", width=50, anchor=tk.CENTER)
    app.results_tree.column("Context", width=500)
    app.results_tree.pack(fill=tk.BOTH, expand=True)
    
    # 添加滚动条
    scrollbar = ttk.Scrollbar(results_frame, orient=tk.VERTICAL, command=app.results_tree.yview)
    app.results_tree.configure(yscroll=scrollbar.set)
    scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    
    # 添加上下文行数选择
    context_frame = ttk.Frame(root)
    context_frame.pack(fill=tk.X, padx=5, pady=5)
    
    ttk.Label(context_frame, text="上下文行数:", font=app.default_font).pack(side=tk.LEFT, padx=5)
    app.context_spinbox = ttk.Spinbox(context_frame, from_=3, to=50, width=5, value=10)
    app.context_spinbox.pack(side=tk.LEFT, padx=5)
    
    # 绑定事件
    app.results_tree.bind("<ButtonRelease-1>", app._on_reference_select)
    app.results_tree.bind("<Double-1>", app._on_item_click)
    
    root.mainloop()